package com.ozo.easy.common.log.aspect;

import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.ozo.easy.common.auth.UserLoginHelper;
import com.ozo.easy.common.log.SysLogDTO;
import com.ozo.easy.common.log.annotation.LogAnno;
import com.ozo.easy.common.log.event.SysLogEvent;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import net.dreamlu.mica.ip2region.core.Ip2regionSearcher;
import net.dreamlu.mica.ip2region.core.IpInfo;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

/**
 * 操作日志记录处理
 *
 * @author ozo
 * @date 2024-12-27
 */
@Slf4j
@Aspect
@Component
public class SysLogAspect {

    /**
     * 环绕通知
     *
     * @param joinPoint
     * @param logAnno
     */
    @SneakyThrows
    @Around(value = "@annotation(logAnno)")
    public Object around(ProceedingJoinPoint joinPoint, LogAnno logAnno) {
        // 日志信息
        long startTime = System.currentTimeMillis();
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();

        SysLogDTO sysLogDTO = new SysLogDTO();
        try {
            sysLogDTO.setOperationUser(UserLoginHelper.getUsername());
        } catch (Exception e) {
            log.error("未登录", e);
        }
        sysLogDTO.setOperationTime(LocalDateTime.now());
        // 业务信息
        sysLogDTO.setModule(logAnno.module());
        sysLogDTO.setOperationName(logAnno.value());
        sysLogDTO.setMethod(className + "." + methodName + "()");
        // 请求信息
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        sysLogDTO.setRequestUrl(request.getRequestURI());
        sysLogDTO.setRequestMethod(request.getMethod());
        // 位置信息
        String ipAddr = ServletUtil.getClientIP(request);
        sysLogDTO.setRequestIp(ipAddr);
        IpInfo ipInfo = SpringUtil.getBean(Ip2regionSearcher.class).memorySearch(ipAddr);
        if (ipInfo != null) {
            sysLogDTO.setRequestLocation(StringUtils.isNotBlank(ipInfo.getCountry()) ? ipInfo.getCountry() + ipInfo.getProvince() + ipInfo.getCity() + ipInfo.getIsp() : ipInfo.getIsp());
        }
        // 请求参数
        if (request.getParameterMap() != null && !request.getParameterMap().isEmpty()) {
            Map<String, String[]> requestParam = new HashMap<>(request.getParameterMap());
            sysLogDTO.setRequestParam(HttpUtil.toParams(requestParam));
        }
        // 请求体
        sysLogDTO.setRequestBody(JSONUtil.toJsonStr(joinPoint.getArgs()));

        try {
            Object obj = joinPoint.proceed();
            sysLogDTO.setSuccessFlag(true);
            // 响应数据
            sysLogDTO.setResponseData(obj == null ? null : JSONUtil.toJsonStr(obj));
            return obj;
        } catch (Exception e) {
            sysLogDTO.setSuccessFlag(false);
            sysLogDTO.setErrorMsg(e.getMessage());
            throw e;
        } finally {
            sysLogDTO.setCostTime(System.currentTimeMillis() - startTime);
            SpringUtil.publishEvent(new SysLogEvent(sysLogDTO));
        }
    }

}
